<!DOCTYPE html>
<html>
<head profile="http://www.w3.org/2005/10/profile">
<link rel="shortcut icon" href="/web/favicon.ico" type="image/x-icon" />
<title>sView Web UI</title>

<script>

var isFirefox = typeof InstallTrigger !== 'undefined';

var myPlayItem   = -1; // currently played item id within playlist
var myListSerial = -1; // playlist serial number
var myVolume     = -1; // volume
var myList;            // playlist content
var myOffCount   = 0;  // offline counter

function postRequest(theUrl, theFunc, theASync) {
  var aReq = new XMLHttpRequest();
  aReq.onreadystatechange = theFunc;
  aReq.open("GET", theUrl, theASync);
  aReq.send();
}

function doPlayPause() { postRequest('play_pause',  function() {}, true); }
function doStop()      { postRequest('stop',        function() {}, true); }
function doListPrev()  { postRequest('prev',        function() {}, true); }
function doListNext()  { postRequest('next',        function() {}, true); }
function doFullWin()   { postRequest('fullscr_win', function() {}, true); }
function doAudioMute() { postRequest('mute',        function() {}, true); }
function doAudioVol()  { postRequest('vol?'  + myVolume,   function() {}, true); }
function doListItem()  { postRequest('item?' + this.myPos, function() {}, true); }

function getAbsolutePosition(theElement) {
  var aPos = { x: theElement.offsetLeft, y: theElement.offsetTop };
  if(theElement.offsetParent) {
    var aTmp = getAbsolutePosition(theElement.offsetParent);
    aPos.x += aTmp.x;
    aPos.y += aTmp.y;
  }
  return aPos;
}

function getRelativeCoordinates(theEvent, theReference) {
  var x, y;
  theEvent = theEvent || window.event;
  var el = theEvent.target || theEvent.srcElement;

  if(!window.opera && typeof theEvent.offsetX != 'undefined') {
    // Use offset coordinates and find common offsetParent
    var aPos = { x: theEvent.offsetX, y: theEvent.offsetY };

    // Send the coordinates upwards through the offsetParent chain.
    var e = el;
    while(e) {
      e.mouseX = aPos.x;
      e.mouseY = aPos.y;
      aPos.x += e.offsetLeft;
      aPos.y += e.offsetTop;
      e = e.offsetParent;
    }

    // Look for the coordinates starting from the reference element.
    var e = theReference;
    var anOffset = { x: 0, y: 0 }
    while(e) {
      if(typeof e.mouseX != 'undefined') {
        x = e.mouseX - anOffset.x;
        y = e.mouseY - anOffset.y;
        break;
      }
      anOffset.x += e.offsetLeft;
      anOffset.y += e.offsetTop;
      e = e.offsetParent;
    }

    // reset stored coordinates
    e = el;
    while(e) {
      e.mouseX = undefined;
      e.mouseY = undefined;
      e = e.offsetParent;
    }
  } else {
    // absolute coordinates
    var aPos = getAbsolutePosition(theReference);
    x = theEvent.pageX - aPos.x;
    y = theEvent.pageY - aPos.y;
  }

  // Subtract distance to middle
  return { x: x, y: y };
}

function doUpdateTitle() {
  postRequest('current?title', function() {
    if(this.readyState == 4 && this.status == 200) {
      var aCurrTitle = this.responseText;
      document.getElementById('stTitle').innerHTML = "Current: " + aCurrTitle;
      if(aCurrTitle.length === 0) {
        document.title = 'sView Web UI';
      } else {
        document.title = aCurrTitle + ' - sView Web UI';
      }

      if(myList && myList.rows.length == 0) {
        myListSerial = -1;
      }
    }
  }, true);
}

function doMakePlaylist(theList) {
  myList = document.createElement('table');
  myList.border = '1';
  myList.width  = '100%';
  myList.height = '100%';
  myList.style.borderCollapse = 'collapse';

  for(var anIter = 0; anIter < theList.length; ++anIter) {
    var anItem = theList[anIter];

    var aLink = document.createElement('a');
    aLink.href = 'javascript:void(0)';
    aLink.innerHTML = anItem;

    var aRow = myList.insertRow(-1);
    aRow.myPos = anIter;
    aRow.onclick = doListItem;
    aRow.myColorPassive = (anIter % 2) ? 'aliceblue' : 'white';
    aRow.style.backgroundColor = aRow.myColorPassive;
    aRow.onmouseover = function() {
      this.myOldColor = this.style.backgroundColor;
      this.style.backgroundColor = 'lightsteelblue';
    };

    aRow.onmouseout = function() {
      this.style.backgroundColor = this.myOldColor;
    };

    if(anIter == myPlayItem) {
      aRow.style.backgroundColor = 'silver';
      aRow.myOldColor = 'silver';
    }

    var aCellId = aRow.insertCell(-1);
    aCellId.width  = '50';
    aCellId.height = '30';
    aCellId.style.verticalAlign = 'middle';
    aCellId.style.textAlign     = 'center';
    aCellId.innerHTML = anIter;

    var aCellText = aRow.insertCell(-1);
    aCellText.height = '30';
    aCellText.style.verticalAlign = 'middle';
    aCellText.style.textAlign     = 'left';
    aCellText.appendChild(aLink);
  }

  var aRoot = document.getElementById('stPlaylist');
  aRoot.innerHTML = "";
  aRoot.appendChild(myList);

  doUpdateTitle();
}

function refreshPlaylist() {
  postRequest('playlist', function() {
    if(this.readyState == 4 && this.status == 200) {
      var aListStr = this.responseText;
      doMakePlaylist(aListStr.split("\n"));
    }
  }, true);
}

function onVolumeClick(theEvent) {
  var aPos = getRelativeCoordinates(theEvent, this);
  myVolume = aPos.x > 98 ? 100 : aPos.x;
  drawVolume();
  doAudioVol();
}

function onVolumeWheel(theEvent) {
  var aDelta = theEvent.detail ? -theEvent.detail : theEvent.wheelDelta / 120;
  var aVolume = myVolume + Number((aDelta > 0) ? 1 : -1);
  if(aVolume < 0 || aVolume > 150 || myVolume < 0) {
    return;
  }

  myVolume = aVolume;
  drawVolume();
  doAudioVol();

  if(theEvent.preventDefault) {
    theEvent.preventDefault();
  } else {
    return false;
  }
}

function drawVolume() {
  var aCanvas = document.getElementById('stVolumeCanvas');
  var aCtx    = aCanvas.getContext('2d');
  var aWidth  = 100;

  aCtx.beginPath();
  aCtx.rect(1, 1, aWidth - 2, 18);
  aCtx.fillStyle = 'yellow';
  aCtx.fill();

  aCtx.lineWidth = 1;
  aCtx.strokeStyle = 'black';
  aCtx.stroke();

  var aFilled = (myVolume / 100) * (aWidth - 2);
  aFilled = Math.max(aFilled, 0);
  aFilled = Math.min(aFilled, aWidth - 2);

  aCtx.beginPath();
  aCtx.rect(1, 1, aFilled, 18);
  aCtx.fillStyle = 'blue';
  aCtx.fill();

  aCtx.font = 'bold 8pt Calibri';
  aCtx.textAlign = 'center';
  aCtx.fillStyle = 'black';
  aCtx.fillText(myVolume + '%', aWidth / 2 + 1, 15);
  aCtx.fillStyle = myVolume <= 100 ? 'white' : 'red';
  aCtx.fillText(myVolume + '%', aWidth / 2, 14);
}

function doRefresh() {
  postRequest('current?id', function() {
    if(this.readyState != 4 || this.status != 200) {
      if(myOffCount >= 10) {
        document.getElementById('stOffline').innerHTML = "[offline]";
      }
      ++myOffCount;
      return;
    }
    if(myOffCount >= 10) {
      document.getElementById('stOffline').innerHTML = "";
    }
    myOffCount = 0;

    var aCurrArr = this.responseText.split(":");
    var aCurrListId = aCurrArr[0];
    var aCurrItemId = aCurrArr[1];
    var aCurrVolume = Number(aCurrArr[2]);
    if(aCurrVolume != myVolume) {
      myVolume = aCurrVolume;
      drawVolume();
    }

    if(aCurrListId == myListSerial
    && aCurrItemId == myPlayItem) {
      return;
    }

    // update entire playlist
    if(aCurrListId != myListSerial) {
      myListSerial = aCurrListId;
      myPlayItem   = aCurrItemId;
      postRequest('playlist', function() {
        if(this.readyState == 4 && this.status == 200) {
          var aListStr = this.responseText;
          doMakePlaylist(aListStr.split("\n"));
        }
      }, true);
      return;
    }

    if(aCurrItemId == myPlayItem) {
      return;
    }

    // hi-light currently played item
    if(myList) {
      if(myPlayItem >= 0 && myPlayItem < myList.rows.length) {
        var aRowPrev = myList.rows[myPlayItem];
        aRowPrev.style.backgroundColor = aRowPrev.myColorPassive;
      }
      if(aCurrItemId >= 0 && aCurrItemId < myList.rows.length) {
        var aRow = myList.rows[aCurrItemId];
        aRow.style.backgroundColor = 'silver';
        aRow.myOldColor = 'silver';
      }
    }
    myPlayItem = aCurrItemId;
    doUpdateTitle();
  }, true);
}

window.setInterval(function() { doRefresh() }, 2000);

</script>

</head>
<body>

<h2>sView - Remote Control (<span id="stVer"></span>) <span id="stOffline"></span></h2>
<script>
  postRequest('version', function() {
    if(this.readyState == 4 && this.status == 200) {
      document.getElementById('stVer').innerHTML = this.responseText;
    }
  }, false);
</script>

<table border='0' style='position: fixed; margin-top: 0px; right: 0px; opacity: 0.6' bgcolor="#AAAAAA">
<tr align='right'><td>
  <table>
  <tr align='center'><td colspan='6'><div id='stTitle'></div></td></tr>
  <tr align='center'>
    <td><a href="javascript:void(0)" onclick="doPlayPause();return false;">
      <svg width='64' height='64'> <image width='64' height='64' xlink:href='textures/actionVideoPlayBlue.svg'       src='textures/actionVideoPlayBlue64.png'       alt='Play/Pause' /></svg>
    </a></td>
    <td><a href="javascript:void(0)" onclick="doListPrev();return false;">
      <svg width='64' height='64'> <image width='64' height='64' xlink:href='textures/actionVideoPreviousBlue.svg'   src='textures/actionVideoPreviousBlue64.png'   alt='Previous' /></svg>
    </a></td>
    <td><a href="javascript:void(0)" onclick="doListNext();return false;">
      <svg width='64' height='64'> <image width='64' height='64' xlink:href='textures/actionVideoNextBlue.svg'       src='textures/actionVideoNextBlue64.png'       alt='Next' /></svg>
    </a></td>
    <td><a href="javascript:void(0)" onclick="doFullWin();return false;">
      <svg width='64' height='64'> <image width='64' height='64' xlink:href='textures/actionVideoFullscreenBlue.svg' src='textures/actionVideoFullscreenBlue64.png' alt='Fullscreen/Windowed' /></svg>
    </a></td>
    <td><canvas id="stVolumeCanvas" width="100" height="20"></canvas></td>
    <td><button onclick="doAudioMute()">Mute</button></td>
  </tr></table>
</td></tr></table>

<div id='stPlaylist'></div>
<script>
  // setup mouse events
  var aVolCtrl = document.getElementById('stVolumeCanvas');
  aVolCtrl.ondragstart = function() { return false; }; // block dragging
  aVolCtrl.myMouseTrack = 0;
  aVolCtrl.onmousedown  = onVolumeClick;
  if(aVolCtrl.addEventListener) {
    aVolCtrl.addEventListener(isFirefox ? 'DOMMouseScroll' : 'mousewheel', onVolumeWheel, false);
  }

  // first update
  doRefresh();
</script>

</body>
</html>
